<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>ZJCA客户端 制证DEMO</title>
	
	<!--UI式样文件-->
	<link rel="stylesheet" type="text/css" href="./style.css">
	
    <!--ZJCA客户端相关的JS文件-->
	<script src="../../zjca_cmt/jquery.min.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_cert.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_key.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_com.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_websocket.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_def.js" type="text/javascript"></script>
	<script src="../../zjca_cmt/zjcacmt_err.js" type="text/javascript"></script>
</head>

<script type="text/javascript">

	/* ZJCA 客户端插件对象 */
	var g_ZjcaCMT = null;
	/* 当前枚举到的设备列表 */
	var g_UsingDeviceArray = null
	/* 当前使用的设备索引 */
	var g_UsingDeviceIndex = -1;
	/* 当前使用的证书业务类型 */
	var g_UsingApplyType = 1;
	
	/*
	 *	页面初始化
	 */
	window.onload = function() {
		//创建ZJCA客户端控件对象
		g_ZjcaCMT = new zjca_CMT(onCallbackKeyEvent, null);
		
		//设置客户端交互协议，在初始之前设置生效
		g_ZjcaCMT.setProtocol(PROTOCOL_HTTPS);
		
		//初始化ZJCA控件对象
		var resp = g_ZjcaCMT.init(ZJCA_PRODUCT_CMT, 1);
		if (resp.code != 0) {
			alert("初始化ZJCA客户端失败！\n错误信息：" + resp.msg);
		}else {
			//获取设备列表
			resp = g_ZjcaCMT.getKeyList(false);
			if (resp.code == 0) {
				FillDeviceList(resp.res);
			}else { //获取设备列表失败
				ShowErrorMessage("g_ZjcaCMT.getKeyList()失败!", resp.code);
			}
		}
	}
	/*
	 *	页面关闭
	 */
	window.onunload = function () {
		/* 释放接口 */
		if (g_ZjcaCMT) {
			g_ZjcaCMT.finaled();
		}
	}
	/*
	 *  列出设备
	 */
	function FillDeviceList(keyArray) {			
		// 删除老的选项
		var selKeyCtrl = document.getElementById('selKeys');
		var itemCount = selKeyCtrl.options.length;
		for (var n = 0; n < itemCount; n++) {
			selKeyCtrl.options.remove(0);
		}
		
		// 保存当前选择的设备
		var selDeviceSN;
		if (g_UsingDeviceIndex >= 0) {			
			selDeviceSN = g_UsingDeviceArray[g_UsingDeviceIndex].getSN();
		}
		
		// 更新列表
		g_UsingDeviceArray = keyArray;
		if (g_UsingDeviceArray && g_UsingDeviceArray.length > 0) {
			selKeyCtrl.options.add(new Option('请选择UKey设备', -1));

			for (var n = 0; n < g_UsingDeviceArray.length; n++) {
				var keySN = g_UsingDeviceArray[n].getSN();
				var keyLabel = g_UsingDeviceArray[n].getLabel();
				var text = keyLabel + "(" + keySN + ")";
				selKeyCtrl.options.add(new Option(text, n));
			}
		}
		else {
			selKeyCtrl.options.add(new Option('未发现任何ZJCA UKey设备', -1));
		}

		// 设置选中的设备
		var i = 0;
		if (g_UsingDeviceIndex >= 0) {
			for (i = 0; i < g_UsingDeviceArray.length; i++) {
				if (selDeviceSN == g_UsingDeviceArray[i].getSN()) {
					document.form1.selKeys.options[i].selected = true;
					g_UsingDeviceIndex = i;
					break;
				}
			}
		}
		if (i == g_UsingDeviceArray.length) {
			document.form1.selKeys.options[0].selected = true;
			OnSelKeyChanged();
		}
	}	 
	/*
	 *  选择设备
	 */
	function OnSelKeyChanged() {
		g_UsingDeviceIndex = document.getElementById("selKeys").value;
	}	 
	/*
	 *  选择制证业务类型
	 */
	function OnSelApplyTypeChanged() {
		g_UsingApplyType = document.getElementById("selApplyType").value;
		g_UsingApplyType = parseInt(g_UsingApplyType);
		
		switch (g_UsingApplyType) {
		case 1:	//新领/补办/重发
			document.getElementById("csrDiv").style.display="";
			document.getElementById("delayDiv").style.display="none";
			document.getElementById("newKeyPair").checked = true;
			//			
			document.getElementById("exchCert").disabled="";
			document.getElementById("exchKeyPair").disabled="";
			document.getElementById("symmCipher").disabled="";
			document.getElementById("symmOid").disabled="";
			document.getElementById("authCode").disabled="";
			break;
		case 2:	//变更
			document.getElementById("csrDiv").style.display="";
			document.getElementById("delayDiv").style.display="none";
			document.getElementById("newKeyPair").checked = false;
			//			
			document.getElementById("exchCert").disabled="";
			document.getElementById("exchKeyPair").disabled="disabled";
			document.getElementById("symmCipher").disabled="disabled";
			document.getElementById("symmOid").disabled="disabled";
			document.getElementById("authCode").disabled="disabled";
			break;
		case 3:	//延期
			document.getElementById("csrDiv").style.display="none";
			document.getElementById("delayDiv").style.display="";
			//			
			document.getElementById("exchCert").disabled="";
			document.getElementById("exchKeyPair").disabled="disabled";
			document.getElementById("symmCipher").disabled="disabled";
			document.getElementById("symmOid").disabled="disabled";
			document.getElementById("authCode").disabled="disabled";
			break;
		case 4:	//单证书
			document.getElementById("csrDiv").style.display="";
			document.getElementById("delayDiv").style.display="none";
			//			
			document.getElementById("exchCert").disabled="disabled";
			document.getElementById("exchKeyPair").disabled="disabled";
			document.getElementById("symmCipher").disabled="disabled";
			document.getElementById("symmOid").disabled="disabled";
			document.getElementById("authCode").disabled="disabled";
			break;
		}
	}	
	/*
		生成证书请求
	*/
	function OnBtnGenCertReq(){	
		if (g_UsingDeviceIndex < 0) {
			alert("请选择设备！");
			return;
		}
		if (g_UsingDeviceIndex >= g_UsingDeviceArray.length) {
			alert("选择的设备错误！");
			return;
		}
		
		var bits = 2048;
		var certAlg  = document.getElementById("certType").value;	 //1:RSA 2:SM2
		certAlg = parseInt(certAlg);
		
		var newKey = document.getElementById('newKeyPair').checked;		
		if (1 == certAlg) {
			bits = 2048;
		}else if (2 == certAlg) {
			bits = 256;
		}else {
			alert("证书算法类型错误!");	
			return;
		}
		
		// 生成证书请求
		var resp = g_ZjcaCMT.genCertReq(g_UsingDeviceIndex, 	//设备序号
									    certAlg, 				//证书算法
										newKey,					//是否重新生成签名密钥对
										bits,					//密钥位数
										"CN=test"				//主题项，可以任意填
										);
		if (0 == resp.code) {	//生成证书请求成功
			document.form1.csr.value = resp.res;				
		}else {	//生成证书请求失败
			if (0x81000007 != zjca_GetErrHexCode(resp.code)) { //如果不是用户取消操作,则显示错误信息
				ShowErrorMessage("g_ZjcaCMT.genCertReq()失败!", resp.code);
			}
		}
	}
	/*
		安装证书
	*/
	function OnBtnInstallCert(){
		var signCert = "";
		var exchCert = "";
		var exchKeyPair = "";
		var symmCipher = "";
		var symmOid = "";
		var authCode = "";
		var symmAlg = 0;
		
		if (g_UsingDeviceIndex < 0) {
			alert("请选择设备！");
			return;
		}
		if (g_UsingDeviceIndex >= g_UsingDeviceArray.length) {
			alert("选择的设备错误！");
			return;
		}
		
		//证书算法
		var certAlg  = document.getElementById("certType").value;	 //1:RSA 2:SM2
		certAlg = parseInt(certAlg);
		
		//签名证书
		signCert = document.getElementById('signCert').value;
		if (signCert.length == 0) {
			alert("签名证书为空！");
			return;
		}
		
		//加密证书(单证书无此项)
		if (g_UsingApplyType != 4) {
			exchCert = document.getElementById('exchCert').value;
			if (exchCert.length == 0) {
				alert("加密证书为空！");
				return;
			}
		}
		
		//仅“新领/补办/重发”时，有加密密钥对和授权码
		if (g_UsingApplyType == 1) {
			//加密密钥密文
			exchKeyPair = document.getElementById('exchKeyPair').value;
			if (exchKeyPair.length == 0) {
				alert("加密密钥密文为空！");
				return;
			}
			//对称密钥(仅RSA证书需要)
			if (certAlg  == 1) {			
				symmCipher = document.getElementById('symmCipher').value;
				if (symmCipher.length == 0) {
					alert("对称密钥为空！");
					return;
				}
			}
			//对称密钥算法(仅RSA证书需要)
			if (certAlg  == 1) {	
				symmOid = document.getElementById('symmOid').value;
				if (symmOid.length == 0) {
					alert("对称密钥算法为空！");
					return;
				}	
			}			
			//授权码
			authCode = document.getElementById('authCode').value;
			if (authCode.length == 0) {
				alert("授权码为空！");
				return;
			}
		}
		
		// 安装证书
		var resp;
		switch (parseInt(g_UsingApplyType)) {
		case 1:
			resp = g_ZjcaCMT.importCertAndEncKeyPair(g_UsingDeviceIndex, certAlg, signCert, exchCert, exchKeyPair, symmOid, symmCipher, authCode);
			break;
		case 2:
		case 3:
			resp = g_ZjcaCMT.importDualCert(g_UsingDeviceIndex, certAlg, signCert, exchCert);
			break;
		case 4:
			resp = g_ZjcaCMT.importCert(g_UsingDeviceIndex, certAlg, signCert);
			break;
		default:
			alert("证书业务类型错误！");
		}
		
		// 安装证书成功
		if (resp.code == 0) {
			g_ZjcaCMT.getKeyList(true);	//强刷设备列表，从而让客户端能自动显示新的证书(无需手动把插介质)。
			alert("安装证书成功！");	
		}
		// 安装证书失败
		else {	
			if (0x81000007 != zjca_GetErrHexCode(resp.code)) { //如果不是用户取消操作,则显示错误信息
				ShowErrorMessage("证书安装失败!", resp.code);
			}
		}		
	}
	//	刷新
	function OnRefreshKeyList(force) {
		if (1 != force) {
			var resp = g_ZjcaCMT.getKeyList(false);	
			if (resp.code == 0) {
				FillDeviceList(resp.res);
			}		
		}else {
			g_ZjcaCMT.getKeyList(true);	
		}
	}
	
	//	设备事件响应函数
	function onCallbackKeyEvent(type, index, name) {
		// 重新获取设备列表
		var resp = g_ZjcaCMT.getKeyList(false);	
		if (resp.code == 0) {
			FillDeviceList(resp.res);
		}	
	}
	//	函数错误响应函数
	function ShowErrorMessage(msg, code) {
		var errCode = zjca_GetErrHexCode(code);
		var errTxt = zjca_GetErrTxt(code);
	
		var errMsg = msg;
		errMsg += "\n";
		errMsg += "错误代码：";
		errMsg += errCode;
		errMsg += "\n";
		errMsg += "错误信息：";
		errMsg += errTxt;
		alert(errMsg);
	}	
</script>

<body>
	<div class="app">
		<h2>ZJCA客户端 制证DEMO</h2>
		<form name="form1" action="">
			<fieldset>
				<legend>帮助说明：</legend>
				<td>制证操作包含“新领/补办/重发”、“变更”、“延期”和“单证书”，主要流程说明如下：</td><br>
				<td>1、新建JS对象zjca_CMT；</td><br>
				<td>2、调用JS API：zjca_CMT.init()初始化；</td><br>
				<td>3、待初始化函数返回后，调用JS API：zjca_CMT.getKeyList()获取设备列表；</td><br>
				<td>4、选择一个设备；</td><br>
				<td>5、选择证书业务类型(其中：“新领/补办/重发”需要生成CSR、“变更”也需要生成CSR但要求不重新生成密钥对；"延期"不需要生成CSR；"单证书"也有以上操作，为了简单起见，没有全部列出。)；</td><br>
				<td>6.1、(新领/补办/重发/变更业务)调用JS API：zjca_CMT.genCertReq()生成证书请求(CSR|req)，等待返回结果之后将结果发送CA服务器；</td><br>
				<td>6.2、(延期业务)调用JS API：zjca_CMT.getCertList()返回介质内的证书，并将证书序列号发送给CA服务器；</td><br>
				<td>7、等待CA服务器的结果，将返回的制证结果解析成签名证书、加密证书、加密密钥对、对称算法、对称密钥密文和授权码；</td><br>
				<td>8.1、(新领/补办/重发业务)调用JS API：zjca_CMT.importCertAndEncKeyPair()，导入双证书和加密密钥对；</td><br>
				<td>8.2、(变更/延期业务)调用JS API：zjca_CMT.importDualCert()，导入双证书；</td><br>
				<td>8.3、(单证书业务)调用JS API：zjca_CMT.importSignCert()，导入签名证书；</td><br>
				<td>9、在页面关闭时，调用zjca_CMT.finaled()反初始化。</td><br>
			</fieldset>
			<br>
			<fieldset>
				<legend>制证:</legend>
				<div>
					选择介质：<select id="selKeys" name="selKeys" onchange="OnSelKeyChanged()"></select>
					<input id="btnUpdate" type="button" value="普通刷新" onclick="OnRefreshKeyList(0)">
					<input id="btnRefresh" type="button" value="强制刷新" onclick="OnRefreshKeyList(1)">
				</div>
				<br>
				<div>
					选择业务：
					<select name="selApplyType" id="selApplyType" onchange="OnSelApplyTypeChanged()">
						<option value=1>新领/补办/重发</option>
						<option value=2>变更</option>
						<option value=3>延期</option>
						<option value=4>单证书</option>
					</select>
				</div>	
				<br>			
				<div id="csrDiv" name="csrDiv" style="display: dispaly;">
					<input id="btnGenCSR" type="button" value="生成证书请求" onclick="OnBtnGenCertReq()">
					<select name="certType" id="certType">
						<option value=1>RSA</option>
						<option value=2>SM2</option>
					</select>

					<label for="newKeyPair">
						<input type="checkbox" name="" id="newKeyPair" checked="true">重新生成密钥对
					</label>

					<textarea name="csr" id="csr"></textarea>
					<td>(请将制证请求(CSR|reqCode)发送给CA服务器，并将返回的制证结果填入下面输入框中，再点击"安装证书"按钮!)</td>
				</div>
				<div id="delayDiv" name="delayDiv" style="display: none;">
					<td>(延期不需要生成CSR，请将证书序列号(SN)发送给CA服务器，并将返回的制证结果填入下面输入框中，再点击"安装证书"按钮!)</td>
				</div>
			</fieldset>

			<fieldset>
				<legend>制证数据:</legend>
				<ul>
					<li>
						<label>签名证书：</label>
						<textarea id="signCert"></textarea>
					</li>
					<li>
						<label>加密证书：</label>
						<textarea id="exchCert"></textarea>
					</li>
					<li>
						<label>加密私钥密文：</label>
						<textarea id="exchKeyPair"></textarea>
					</li>
					<li>
						<label>对称密钥密文：</label>
						<textarea id="symmCipher"></textarea>
					</li>
					<li>
						<label>对称密钥算法：</label>
						<textarea id="symmOid"></textarea>
					</li>
					<li>
						<label>授权码：</label>
						<textarea id="authCode"></textarea>
					</li>
				</ul>
				
				<input id="install" type="button" value="安装证书" onclick="OnBtnInstallCert()">
			</fieldset>
		</form>
	</div>
</body>
</html>